package com.langangkj.tools.redis.config;

import com.langangkj.tools.redis.config.properties.RedisSyncConfigProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;

/**
 * @author ZhouChuGang
 * @version 1.0
 * @project redis-sync-tools
 * @date 2020/4/23 15:46
 * @Description 需要同步的redis配置
 */
@Slf4j
@Configuration
@EnableConfigurationProperties(RedisSyncConfigProperties.class)
public class RedisSyncConfig {

    @Autowired
    private RedisSyncConfigProperties redisSyncConfigProperties;

    /**
     * 创建redisTemplate连接模板
     *
     * @return
     */
    @Bean("desRedisTemplate")
    public RedisTemplate<byte[], byte[]> redisTemplate2() {
        RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.setKeySerializer(RedisSerializer.byteArray());
        redisTemplate.setHashKeySerializer(RedisSerializer.byteArray());
        redisTemplate.setValueSerializer(RedisSerializer.byteArray());
        redisTemplate.setHashValueSerializer(RedisSerializer.byteArray());
        return redisTemplate;
    }

    /**
     * 连接配置
     *
     * @return
     */
    private RedisConnectionFactory redisConnectionFactory() {
        log.info("redis配置参数:{}", redisSyncConfigProperties);
        //连接池配置
        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxTotal(redisSyncConfigProperties.getPool().getMaxTotal());
        genericObjectPoolConfig.setMaxWaitMillis(redisSyncConfigProperties.getPool().getMaxWait());
        genericObjectPoolConfig.setMaxIdle(redisSyncConfigProperties.getPool().getMaxIdle());
        genericObjectPoolConfig.setMinIdle(redisSyncConfigProperties.getPool().getMinIdle());
        //redis客户端配置
        LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder().commandTimeout(Duration.ofSeconds(redisSyncConfigProperties.getTimeOut()));
        builder.poolConfig(genericObjectPoolConfig);
        LettuceClientConfiguration lettuceClientConfiguration = builder.build();
        if (StringUtils.isEmpty(redisSyncConfigProperties.getHosts())) {
            throw new IllegalArgumentException("主机地址不能为空");
        }
        //集群模式
        if (redisSyncConfigProperties.isCluster()) {
            List<String> hostList = Arrays.asList(StringUtils.commaDelimitedListToStringArray(redisSyncConfigProperties.getHosts()));
            if (hostList.isEmpty()) {
                throw new IllegalArgumentException("输入的主机列表不能为空:" + redisSyncConfigProperties.getHosts());
            }
            RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(hostList);
            redisClusterConfiguration.setMaxRedirects(redisSyncConfigProperties.getMaxRedirects());
            if (!StringUtils.isEmpty(redisSyncConfigProperties.getPassword())) {
                redisClusterConfiguration.setPassword(redisSyncConfigProperties.getPassword());
            }
            //根据配置和客户端配置创建连接工厂
            LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
            lettuceConnectionFactory.afterPropertiesSet();
            return lettuceConnectionFactory;
        }

        //单机模式
        String[] split = redisSyncConfigProperties.getHosts().split(":");
        if (split.length != 2) {
            throw new IllegalArgumentException("单节点主机端口配置错误:" + redisSyncConfigProperties.getHosts());
        }
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(split[0], Integer.parseInt(split[1]));
        redisStandaloneConfiguration.setDatabase(redisSyncConfigProperties.getDbIndex());
        if (!StringUtils.isEmpty(redisSyncConfigProperties.getPassword())) {
            redisStandaloneConfiguration.setPassword(redisSyncConfigProperties.getPassword());
        }
        //根据配置和客户端配置创建连接
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, lettuceClientConfiguration);
        lettuceConnectionFactory.afterPropertiesSet();
        return lettuceConnectionFactory;
    }

}